package com.sl.sdn.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.stream.StreamUtil;
import com.sl.sdn.dto.OrganDTO;
import com.sl.sdn.dto.TransportLineNodeDTO;
import com.sl.sdn.enums.OrganTypeEnum;
import org.neo4j.driver.internal.value.PathValue;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class CypherUtil {
    private CypherUtil() {

    }

    public static TransportLineNodeDTO postting(Neo4jClient neo4jClient, String cypher, Long startBid, Long endBid) {
        return neo4jClient.query(cypher)
                .bind(startBid).to("startId") // 绑定业务id
                .bind(endBid).to("endId")
                .fetchAs(TransportLineNodeDTO.class)// 最后需要返回的对象的字节码对象
                .mappedBy((typeSystem, record) -> {
                    // 对结果进行封装处理
                    PathValue path = (PathValue) record.get("path");
                    TransportLineNodeDTO dto = new TransportLineNodeDTO();
                    // 获取结点数据
                    List<OrganDTO> organDTOS = StreamUtil.of(path.asPath().nodes())
                            .map(node -> {
                                OrganDTO organDTO = BeanUtil.toBean(node.asMap(), OrganDTO.class);
                                // 取第一个标签作为结点类型
                                OrganTypeEnum organTypeEnum = OrganTypeEnum.valueOf(CollUtil.getFirst(node.labels()));
                                organDTO.setType(organTypeEnum.getCode());
                                // 获取经纬度信息
                                organDTO.setLongitude(BeanUtil.getProperty(node.asMap().get("location"), "x"));
                                organDTO.setLatitude(BeanUtil.getProperty(node.asMap().get("location"), "y"));
                                return organDTO;
                            })
                            .collect(Collectors.toList());
                    dto.setNodeList(organDTOS);
                    // 获取总成本
                    double costSum = StreamUtil.of(path.asPath().relationships())
                            .mapToDouble(r -> {
                                Double cost = Convert.toDouble(r.asMap().get("cost"), 0d);
                                return cost;
                            }).sum();
                    dto.setCost(costSum);
                    return dto;
                })
                .one()
                .orElse(null);
    }
}
